package com.ocm.tourism.core.service;

import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

import com.ocm.tourism.core.dao.BusinessDao;
import com.ocm.tourism.core.dao.CulinaryCultureDao;
import com.ocm.tourism.core.dao.HotelDao;
import com.ocm.tourism.core.dao.ParticipantDao;
import com.ocm.tourism.core.domain.Advertisement;
import com.ocm.tourism.core.domain.AuditBusinessAdvs;
import com.ocm.tourism.core.domain.Business;
import com.ocm.tourism.core.domain.BusinessType;
import com.ocm.tourism.core.domain.CulinaryCulture;
import com.ocm.tourism.core.domain.Distance;
import com.ocm.tourism.core.domain.FoodStall;
import com.ocm.tourism.core.domain.Hotel;
import com.ocm.tourism.core.domain.MapInfo;
import com.ocm.tourism.core.domain.Participant;
import com.ocm.tourism.core.domain.Room;
import com.ocm.tourism.core.domain.SaleOff;
import com.ocm.tourism.core.domain.TransalationType;
import com.ocm.tourism.core.jdbc.AdvertisementDb;
import com.ocm.tourism.core.model.ComparisonType;
import com.ocm.tourism.core.model.FieldCriteria;
import com.ocm.tourism.core.model.SearchCriteria;
import com.ocm.tourism.core.util.UserUtil;
import com.ocm.tourism.core.util.ValueUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("businessService")
public class BusinessServiceImpl implements BusinessService {

   @Autowired
   BusinessDao businessDao;

   @Autowired
   HotelDao hotelDao;

   @Autowired
   CulinaryCultureDao culinaryCultureDao;

   @Autowired
   AdvertisementDb advertisementDb;

   @Autowired
   ParticipantDao participantDao;

   @Autowired
   AuditService auditService;

   public void deleteBusiness(Business business) {
      businessDao.remove(business.getId());
   }

   public Business findBusiness(Long id) {
      return businessDao.find(id);
   }

   @Transactional(readOnly=false, propagation=Propagation.REQUIRED)
   public void saveBusiness(Business business) {
      if (business.getId() == null || business.getId() == 0){
         Participant participant = participantDao.find(UserUtil.currentParticipantId());
         business.setParticipant(participant);
         business.setCreatedDate(new Date(System.currentTimeMillis()));
         businessDao.save(business);
      }else
         businessDao.update(business);
   }

   @Override
   public List<Hotel> findHotels() {
      List<Hotel> businesses = this.hotelDao.findAll();
      return businesses;
   }

   @Override
   public List<Hotel> findSaleOffHotels(int firstResult, int maxResults) {
      List<Hotel> hotels = this.advertisementDb.getSaleOffHotels(firstResult, maxResults);
      return hotels;
   }

   @Override
   public long countHotels() {
      long count = this.hotelDao.count();
      return count;
   }

   @Override
   public List<Hotel> findHotels(int firstResult, int maxResults) {
      List<Hotel> businesses = this.hotelDao.findAll(firstResult, maxResults);
      return businesses;
   }

   @Override
   public List<Room> findRooms(long hotel, int firstResult, int maxResults) {
      List<Room> rooms = this.hotelDao.findAllRooms(hotel,firstResult, maxResults);
      return rooms;
   }

   @Override
   public List<Room> findRooms(long hotel) {
      List<Room> rooms = this.hotelDao.findAllRooms(hotel);
      return rooms;
   }

   @Override
   public Hotel findhotel(Long id) {
      Hotel hotel = this.hotelDao.find(id);
      return hotel;
   }

   @Override
   public Room findRoom(Long id) {
      Room room = this.hotelDao.findRoom(id);
      return room;
   }

   @Override
   public long countRooms(long hotelId) {
      long count = this.hotelDao.countRooms(hotelId);
      return count;
   }

   @Override
   public Advertisement findAdvertisement(Long id) {
      Advertisement advertisement = this.hotelDao.findAdvertisement(id);
      return advertisement;
   }

   @Override
   public SaleOff findSaleOff(Long id) {
      SaleOff saleOff = this.hotelDao.findSaleOff(id);
      return saleOff;
   }

   @Override
   public long countSaleOffs(long hotelId) {
      long count = this.hotelDao.countSaleOffs(hotelId);
      return count;
   }

   @Override
   public List<SaleOff> findSaleOffs(long hotel, int firstResult, int maxResults) {
      List<SaleOff> saleOffs = this.hotelDao.findSaleOffs(hotel, firstResult, maxResults);
      return saleOffs;
   }

   @Override
   public List<Hotel> findHotels(String name, String address, String mobile, String homephone) {
      List<FieldCriteria> criterias = new ArrayList<FieldCriteria>();
      if (!ValueUtil.isEmpty(name)){
         FieldCriteria criteria = new FieldCriteria();
         criteria.setName("name");
         criteria.setValue(name+"%");
         criteria.setComparisonType(ComparisonType.LIKE);
         criterias.add(criteria);
      }
      if (!ValueUtil.isEmpty(address)){
         FieldCriteria criteria = new FieldCriteria();
         criteria.setName("address");
         criteria.setValue("%"+address+"%");
         criteria.setComparisonType(ComparisonType.LIKE);
         criterias.add(criteria);
      }
      if (!ValueUtil.isEmpty(mobile)){
         FieldCriteria criteria = new FieldCriteria();
         criteria.setName("mobilephone");
         criteria.setValue(mobile);
         criteria.setComparisonType(ComparisonType.EQUAL);
         criterias.add(criteria);
      }
      if (!ValueUtil.isEmpty(homephone)){
         FieldCriteria criteria = new FieldCriteria();
         criteria.setName("homephone");
         criteria.setValue(homephone);
         criteria.setComparisonType(ComparisonType.EQUAL);
         criterias.add(criteria);
      }
      List<Hotel> hotels = null;
      if (criterias.size() > 0){
         hotels = this.hotelDao.findHotels(criterias);
      }else{
         hotels = this.hotelDao.findAll();
      }
      return hotels;
   }

   public List<Distance> findDistances(long hotel) {
      List<Distance> distances = this.hotelDao.findDistances(hotel);
      return distances;
   }
   
   public MapInfo findMap(long hotel)
   {
       return this.hotelDao.findMap(hotel);
   }

   @Override
   public List<CulinaryCulture> findRestaurants(int firstResult, int maxResults) {
      List<CulinaryCulture> businesses = this.culinaryCultureDao.find(firstResult, maxResults, BusinessType.RESTAURANT);
      return businesses;
   }
   
   public List<Distance> findDistancesByCalinary(long id) {
      List<Distance> distances = this.culinaryCultureDao.findDistances(id);
      return distances;
   }

   @Override
   public CulinaryCulture findCulinary(long id) {
      CulinaryCulture culinaryCulture = this.culinaryCultureDao.find(id);
      return culinaryCulture;
   }

   @Override
   public List<CulinaryCulture> findRestaurantAdvs(int firstResult, int maxResults) {
      List<CulinaryCulture> culinaryCultures = this.advertisementDb.getRestaurantAdvs(firstResult, maxResults);
      return culinaryCultures;
   }

   @Override
   public long countRestaurants() {
      long count = this.culinaryCultureDao.count(BusinessType.RESTAURANT);
      return count;
   }

   @Override
   public List<CulinaryCulture> findCoffees(int firstResult, int maxResults) {
      List<CulinaryCulture> businesses = this.culinaryCultureDao.find(firstResult, maxResults, BusinessType.COFFEE);
      return businesses;
   }

   @Override
   public List<CulinaryCulture> findCoffeeAdvs(int firstResult, int maxResults) {
      List<CulinaryCulture> culinaryCultures = this.advertisementDb.getCoffeeAdvs(firstResult, maxResults);
      return culinaryCultures;
   }

   @Override
   public long countCoffees() {
      long count = this.culinaryCultureDao.count(BusinessType.COFFEE);
      return count;
   }

   @Override
   public FoodStall findFoodStall(long id) {
      FoodStall foodStall = this.culinaryCultureDao.findFoodStall(id);
      return foodStall;
   }

   @Override
   public List<FoodStall> findFoodStalls(int firstResult, int maxResults) {
      List<FoodStall> foodStalls = this.culinaryCultureDao.findFoodStalls(firstResult, maxResults);
      return foodStalls;
   }

   @Override
   public List<FoodStall> findFoodStallAdvs(int firstResult, int maxResults) {
      List<FoodStall> foodStalls = this.advertisementDb.getFoodStallAdvs(firstResult, maxResults);
      return foodStalls;
   }

   @Override
   public long countFoodStalls() {
      long count = this.culinaryCultureDao.count(BusinessType.FOODSTALL);
      return count;
   }

   @Override
   public List<FoodStall> findFoodStallAdvs(int firstResult, int maxResults, int periodTime) {
      List<FoodStall> foodStalls = this.advertisementDb.getFoodStallAdvs(firstResult, maxResults, periodTime);
      return foodStalls;
   }

   @Override
   public long countFoodStallAdvs(int periodTime) {
      long count = this.advertisementDb.countFoodStallAdvs(periodTime);
      return count;
   }
   
   @Override
   public long countFoodStallAdvs() {
      long count = this.advertisementDb.countFoodStallAdvs();
      return count;
   }

   @Override
   public List<CulinaryCulture> findCulinaryCultures(String name, String address, String mobile, String homephone) {
      List<FieldCriteria> criterias = new ArrayList<FieldCriteria>();
      if (!ValueUtil.isEmpty(name)){
         FieldCriteria criteria = new FieldCriteria();
         criteria.setName("name");
         criteria.setValue(name+"%");
         criteria.setComparisonType(ComparisonType.LIKE);
         criterias.add(criteria);
      }
      if (!ValueUtil.isEmpty(address)){
         FieldCriteria criteria = new FieldCriteria();
         criteria.setName("address");
         criteria.setValue("%"+address+"%");
         criteria.setComparisonType(ComparisonType.LIKE);
         criterias.add(criteria);
      }
      if (!ValueUtil.isEmpty(mobile)){
         FieldCriteria criteria = new FieldCriteria();
         criteria.setName("mobilephone");
         criteria.setValue(mobile);
         criteria.setComparisonType(ComparisonType.EQUAL);
         criterias.add(criteria);
      }
      if (!ValueUtil.isEmpty(homephone)){
         FieldCriteria criteria = new FieldCriteria();
         criteria.setName("homephone");
         criteria.setValue(homephone);
         criteria.setComparisonType(ComparisonType.EQUAL);
         criterias.add(criteria);
      }
      List<CulinaryCulture> culinaryCultures = null;
      if (criterias.size() > 0){
         culinaryCultures = this.culinaryCultureDao.findCulinaryCultures(criterias);
      }else{
         culinaryCultures = this.culinaryCultureDao.find(1, 25, BusinessType.RESTAURANT, BusinessType.COFFEE, BusinessType.FOODSTALL);
      }
      return culinaryCultures;
   }

   @Override
   public List<Business> findHotelViewest(int firstResult, int maxResults) {
      List<Business> businesses = this.advertisementDb.getBusinessViewest(firstResult, maxResults, BusinessType.HOTEL);
      return businesses;
   }

   @Override
   public long countHotelViewest() {
      long count = this.advertisementDb.countBusinessViewest(BusinessType.HOTEL);
      return count;
   }

   @Override
   public List<Hotel> findHotels(SearchCriteria searchCriteria, int firstResult, int maxResults) {
      List<Hotel> hotels = this.hotelDao.findHotels(searchCriteria, firstResult, maxResults);
      return hotels;
   }

   @Override
   public long countSaleOffHotels() {
      long count = this.advertisementDb.countSaleOffHotels();
      return count;
   }

   @Override
   public List<Business> findBusinesses(SearchCriteria searchCriteria, int firstResult, int maxResults) {
      List<Business> businesses = this.businessDao.findBusinesses(searchCriteria, firstResult, maxResults);
      return businesses;
   }

   @Override
   public List<Hotel> findHotelAdvs(int firstResult, int maxResults) {
      List<Hotel> hotels = this.hotelDao.findAdvs(firstResult, maxResults);
      if (hotels.size() > 0){
         Hotel hotel = hotels.get(0);
         AuditBusinessAdvs auditBusinessAdvs = new AuditBusinessAdvs();
         auditBusinessAdvs.setForeignKey(hotel.getId());
         auditBusinessAdvs.setTransalationType(TransalationType.Business);
         this.auditService.saveAuditBusinessAdvs(auditBusinessAdvs);
      }
      return hotels;
   }

   @Override
   public long countHotelAdvs() {
      long count = this.hotelDao.countAdvs();
      return count;
   }
}
